package java6703.lesson13;

public class BankSynchronized6703 {

    //私有变量account，表示要处理的银行账户对象
    static BankAccount6703 account;

    public static void main(String[] args) throws InterruptedException {
        bank6703();
    }

    //在另一个线程中执行的方法：bank6703
    private static void bank6703() throws InterruptedException {
        /*
        步骤：
        ①用名字识别会计与出纳两个线程；
        ②会计线程，存款3次，每次存300元；
        ③出纳线程，取款3次，每次取100元；
        ④为了了解多线程并发存在的问题，在完成存或取款后，修改对应的银行账户余额前，让线程暂停，
        休息一秒，表示读和写的操作占用一定的时长；
        ⑤为了了解同步代码块的设置方法，修改对应的银行账户余额后，让线程暂停，休息一秒，表示线
        程中不使用共享数据的其他代码；
         */

        BankAccount6703 account = new BankAccount6703("212106703", 1000);
        Bank bank = new Bank(account);
        Thread t1 = new Thread(bank, "会计");
        Thread t2 = new Thread(bank, "出纳");

        //输出账户上的开始余额
        System.out.println(account.getBankID() + "账上开始余额：" + account.getBalance() + "元。");
        t1.start();
        t2.start();

        //主线程等待会计线程(t1)、出纳线程(t2)都结束后，输出的余额才是正确的！！
        t1.join();
        t2.join();

        //输出账户上的最终余额
        System.out.println(account.getBankID() + "账上最终余额：" + account.getBalance() + "元。");
    }

    //用方法引用启动多线程
    static void Bank() {
        String name = Thread.currentThread().getName();
        String action = "";
        double money = 0, b = 0;

        //用名字识别会计与出纳两个线程；
        if (name.equals("会计")) {

            //会计线程，存款3次，每次存300元；
            money = 300;
            action = "存入";
        } else if (name.equals("出纳")) {

            //出纳线程，取款3次，每次取100元；
            money = -100;
            action = "取出";
        }

        ////加锁：只允许一个线程执行这段代码
        synchronized (account) {
            for (int i = 1; i <= 3; i++) {

                ////两个线程处理同一个account
                b = account.getBalance() + money;
                System.out.println(name + action + Math.abs(money));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                ////使用共享数据的代码段
                account.setBalance(b);
            }
        }
    }
}

class Bank implements Runnable {
    BankAccount6703 account;

    public Bank(BankAccount6703 account) {
        this.account = account;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        String action = "";
        double money = 0, b = 0;

        //用名字识别会计与出纳两个线程；
        if (name.equals("会计")) {

            //会计线程，存款3次，每次存300元；
            money = 300;
            action = "存入";
        } else if (name.equals("出纳")) {

            //出纳线程，取款3次，每次取100元；
            money = -100;
            action = "取出";
        }

        //加锁：只允许一个线程执行这段代码
        synchronized (this) {
            for (int i = 1; i <= 3; i++) {

                //两个线程处理同一个account
                b = account.getBalance() + money;
                System.out.println(name + action + Math.abs(money));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //使用共享数据的代码段
                account.setBalance(b);
            }
        }
    }
}